// 找出数组里面两个只出现一个内容的数字
// 这一道题目还是可以利用位运算来解决
// 由于所有数字异或了之后,最后剩下的位存在数字的,都是只出现一次的数字所在的位数
// 但是怎么从里面分出来不同数字呢?这就需要分类了
// 由于异或的结果里面,存在两个只出现一次的数字的异或的结合,所以里面的位数如果还能为1的话,其实也就是两个数字的不同之处
// 这样的话,我们可以使用里面有数字的位数(通常使用最后一位有数字的),将所有数字分类为: 该位有值的、该位没值的 两种类型的数
// 这样的话,我们针对这种状况,分别异或了之后,既可以得出只在数组里面出现了一次的两个数字(一分二异或)

// 另外,这里使用了一个新方式求异或结果的最后一位数
// 使用其值的正值和负值相与,即可得出最后一位数的值结果
// 这是怎么实现的呢? 其实这运用了值的正数和负数在内存存储的补码不同的机制
// 举例来说,一个数: 10
// 如果是正值,内存存储值的源码、反码、补码都相同,都是: 0000 0000 0000 1010
// 但是如果是负值,内存存储的补码就要进行转换,就会变成: 0111 1111 1111 0110(补码)
// 我们可以发现,正值和负值的补码,是只有一位相同的,也就是最后正数的最后一位
// 既然这样的话,我们将正值和负值进行与运算,这样的话就会得出: 0000 0000 0000 0010 这样子的值,就可以得出该数字在最后一位的补码了

// 但是呢,这里要考虑一个特殊情况,如果数组的值过于的小,就会溢出,这个时候的补码就只有一位
// 所以,当数字过于小导致溢出的时候,就不用进行与运算了

class Solution 
{
public:
    vector<int> singleNumber(vector<int>& nums) 
    {

        vector<int> ret ;

        ret.resize (2) ;

        int num = 0 ;

        for (auto e : nums)
        {

            num ^= e ;

        }

        int mask = (num == INT_MIN ? num : num & (-num)) ;

        for (auto e : nums)
        {

            if ((mask & e) == 0)
            {

                ret [0] ^= e ;

            }

            else
            {

                ret [1] ^= e ;

            }

        }

        return ret ;
        
    }

};